Attribute Declarations

Attributes can be likened to properties of an element.  Attributes are specific to an element and must be defined within the start tag of the element that they belong to.  We have seen attributes within our employee XML document in the <employee> element.

<employee id="A1234">

In this case, “id” is an attribute.  Like elements, attributes must be declared in the DTD or an error will occur.  An attribute declaration uses the <!ATTLIST> tag and has the following syntax:

<!ATTLIST element.name attribute.definitions>

It is a general practice to keep attribute declarations close the element declarations that they belong to.  Also, if multiple attributes are being declared for a single entity, use multiple lines in declaring them.  This makes the DTD much more readable and easy to understand.  Do not dwell on this code as we are going to explain the syntax in more detail in a moment.  Instead, focus on the <!ATTLIST> tag and its association with the <employee> element.

. . . (omitted)

<!ELEMENT employee (name, position?)>
	<!ATTLIST employee 
			empid CDATA #REQUIRED
			sex   CDATA #REQUIRED>

. . . (omitted)

	<employee empid=”123” sex=”M”>
		<name>John Doe</name>
	</employee>

. . . (omitted)

An attribute declaration accomplishes the following:

It declares the attribute names and element association.

It specifies the attribute type.

It can be used to specify a default value for the attribute.

Each attribute declaration consists of a name and type pair.

Attribute Types

There are three types of attributes that you can create.  These consist of a string type (similar to #PCDATA elements), a tokenized element, and an enumerated attribute.

String Type

Like the name suggests, this attribute type is for storing string values.  Any attribute that is not specifically declared is assumed to be a string type attribute. The syntax for creating a string type attribute is:

<!ATTLIST element.name attribute.name CDATA>

Notice that the CDATA (character data) string is used when declaring string type attributes while #PCDATA (parseable character data) is used when declaring string type elements.  The following example declares an attribute named “empid” that is a string type and is associated with the <employee> element.  

<!ATTLIST employee empid CDATA>

When an <employee> element is created, the “empid” attribute will contain a string value.

<employee empid=”A1234”>

Tokenized Type

Tokenized attributes are attributes whose value consists of one or more tokens that have meaning in XML.  There are seven tokens that you can assign to an attribute.

ID

An ID attribute serves as an identifier for an element.  This is very similar to the ID attribute in HTML.  You may have seen or done something like the following in an HTML document:

<DIV ID=”DIV1”>Some text</DIV>

The ID attribute in HTML allows you to uniquely identify an HTML element.  The same is true in XML, only it must be declared (as all things in XML must).  The syntax for declaring an XML attribute as an ID attribute is:

<!ATTLIST element.name attribute.name ID #REQUIRED>

An ID attribute is very similar to a primary key in a table.  While a primary key uniquely identifies a row in a table, an ID attribute uniquely identifies as element. Thus, an ID attribute value must be unique to the XML document.  An ID value must also conform to XML naming rules, which we discussed previously.

Tip:	You can name an ID attribute any name that you like, but it is standard practice to name the attibute “id” so that it is easy to visually identify.

IDREF

An IDREF attribute is a pointer to an ID attribute value that is declared somewhere else in the document.  In relational database terms, this is similar to a foreign key reference.  They key is that the IDREF attribute value must match the value of an ID attribute somewhere else in the document.  An example is as follows:

. . . (omitted)

<!ELEMENT element1 EMPTY>
	<!ATTLIST element1 id ID #REQUIRED>

<!ELEMENT element2 EMPTY>
	<!ATTLIST element2 el1.id IDREF #REQUIRED>

. . . (omitted)

<element1 id=”A1234”/>

<element2 el1.id=”A1234”/>

. . . (omitted)

File: Chapter 4\IDAttributes.xml
An IDREF attribute is used when an element needs to refer to a specific instance of another element type.  In the above example, <element2> has a direct reference to an instance of an <element1> element by using an IDREF attribute.

Returning to our employee document, let’s add an “id” attribute to the <employee> element so that we can uniquely identify each employee by their unique employee ID.

<!ELEMENT employee (name, position, address, phone)>
<!ATTLIST employee id ID #REQUIRED>

File: Chapter 4\EmployeesWithDTD.xml

IDREFS

An IDREFS attribute has the same purpose as an IDREF attribute except that it can hold multiple ID values.  Each ID value is separated by a space.  Extending our previous example, we could declare a new element type (<element3>) that references multiple (one or more) <element1> instances.

. . . (omitted)

<!ELEMENT element1 EMPTY>
	<!ATTLIST element1 id ID #REQUIRED>

<!ELEMENT element3 EMPTY>
	<!ATTLIST element3 el1.ids IDREF #REQUIRED>

. . . (omitted)

<element1 id=”A1234”/>
<element1 id=”B1234”/>
<element1 id=”C1234”/>

. . . (omitted)

<element3 el1.ids=”A1234 B1234 C1234”/>

. . . (omitted)

File: Chapter 4\IDAttributes.xml

In the above example, <element3> references not one <element1> element, but three.  

The IDREFS attribute type provides a one-to-many type of capability.  A single element can reference multiple instances of other elements.  You may relate this capability to the relational models primary/foreign key concept.  This is partly correct, but the XML implementation is very different.

In our example, the referenced elements were of the same type.  This is not a requirement in XML.  A single IDREFS attribute can not only reference multiple elements, but multiple types of elements as well.  This distinction makes it very different from the relational model in that primary/foreign key relationships relate data between only two tables (element types).  IDREFS do not have this restriction.  This provides more flexibility, but does not provide data integrity as does the relational model.

Warning:	Do not make the mistake of thinking that IDREFS are the same as primary/foreign key relationships in the relational model.  There is no data integrity associated with IDREFS.

Attribute Attributes

There are three keywords in XML that are used to instruct the processor how to treat an attribute.  You have already seen us use two of these in our previous examples.  These keywords always begin with a # character are used at the end of the attribute declaration.

#REQUIRED

This keyword means that the attribute is required.  If it is omitted, the XML processor will generate a fatal error.  When we discussed the ID and IDREFS token types, we used the keyword in the example.  This is because ID attributes are required if the document is to be validated, which we will discuss in the next chapter.

<!ATTLIST element1 id ID #REQUIRED>

#IMPLIED

This keyword instructs the XML processor to the application that no value was specified if the attribute was not assigned.  We first saw implied attributes in the NMTOKENS example.

<!ELEMENT element1 ( #PCDATA )>
<!ATTLIST element1 attr1 NMTOKEN #IMPLIED>
<!ATTLIST element1 attr2 NMTOKENS #IMPLIED>

If either the “attr1” and “attr2” attributes are left out, the processor reports it the application and assumes that it knows how to deal with it.

#FIXED

This keyword is used to create a text constant.  The syntax is:

<!ATTLIST element.name attribute.name 
          attribute.type #FIXED “default value”>

Examine the following statement:

<!ATTLIST form method CDATA #FIXED “POST”>

The <form> element now has an attribute called “method”.  This attribute can only have one value: POST.  The result is that the following statement is valid, and any deviation from it will result in the XML processor generating a fatal error.

<form method=”POST”>

This is actually a clever example, because if you know HTML, you know that the <form> tag has a “method” attribute, and it must be set to “POST” to function correctly.  This is a good example of using one markup language to define another markup language (i.e. XML to define HTML).